package net.dotool.file;

import java.io.Closeable;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import net.dotool.IoTools;

/**
 * @author 李岩飞
 * @email eliyanfei@126.com	
 * 2018年1月15日 下午8:56:22
 * 
 */
public class WatchMonitor extends Thread implements Closeable {
	private WatchService watchService;
	private IWatch watch;
	private boolean isClose = false;
	private List<WatchEvent.Kind<?>> eventList = new ArrayList<WatchEvent.Kind<?>>();
	private String fileName;

	public WatchMonitor(Path path, IWatch watch, String fileName, WatchEvent.Kind<?>... events) {
		try {
			this.fileName = fileName;
			if (events == null || events.length == 0) {
				events = new WatchEvent.Kind<?>[] { StandardWatchEventKinds.OVERFLOW, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE };
			}
			this.watch = watch;
			eventList.addAll(Arrays.asList(events));
			watchService = FileSystems.getDefault().newWatchService();
			path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void run() {
		while (isClose == false) {
			try {
				WatchKey watchKey = watchService.take();
				if (watchKey != null) {
					List<WatchEvent<?>> events = watchKey.pollEvents(); //获取所有得事件
					for (WatchEvent<?> event : events) {
						Path path = (Path) event.context();
						String modiName = path.getFileName().toString();
						WatchEvent.Kind<?> kind = event.kind();
						if (kind == StandardWatchEventKinds.OVERFLOW && eventList.contains(kind) && fileName == null) {
							watch.onOverflow(event, path);
							continue;
						}
						if (kind == StandardWatchEventKinds.ENTRY_CREATE && eventList.contains(kind) && fileName == null) {
							watch.onCreate(event, path);
						} else if (kind == StandardWatchEventKinds.ENTRY_MODIFY && eventList.contains(kind)) {
							if (fileName != null) {
								if (fileName.equals(modiName)) {
									watch.onModify(event, path);
								}
							} else {
								watch.onModify(event, path);
							}
						} else if (kind == StandardWatchEventKinds.ENTRY_DELETE && eventList.contains(kind)) {
							if (fileName != null) {
								if (fileName.equals(modiName)) {
									watch.onDelete(event, path);
								}
							} else {
								watch.onDelete(event, path);
							}
						}
					}
					watchKey.reset();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		try {
			close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void setClose(boolean isClose) {
		this.isClose = isClose;
	}

	@Override
	public void close() throws IOException {
		IoTools.closeIos(watchService);
	}
}
